package com.um.jdy.platform.recharge.manager;

import cn.hutool.core.date.DateUtil;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.um.jdy.baofu.api.BaofuPayService;
import com.um.jdy.common.baofu.entity.po.BaofuRefund;
import com.um.jdy.common.baofu.service.BaofuRefundService;
import com.um.jdy.common.finance.entity.po.PlatformBill;
import com.um.jdy.common.finance.entity.po.PlatformProfitBill;
import com.um.jdy.common.finance.entity.po.UserBill;
import com.um.jdy.common.finance.enums.FinancialEnum;
import com.um.jdy.common.finance.service.PlatformBillService;
import com.um.jdy.common.finance.service.PlatformProfitBillService;
import com.um.jdy.common.finance.service.UserBillService;
import com.um.jdy.common.member.entity.po.RechargeOrder;
import com.um.jdy.common.member.entity.po.Wallet;
import com.um.jdy.common.member.enums.PayEnum;
import com.um.jdy.common.member.service.MemberUserService;
import com.um.jdy.common.member.service.RechargeOrderService;
import com.um.jdy.common.member.service.WalletService;
import com.um.jdy.common.commons.manager.WxManager;
import com.um.jdy.platform.recharge.entity.vo.RechargeOrderItemVO;
import com.um.springboot.starter.entity.Page;
import com.um.springboot.starter.exception.ServiceException;
import com.um.springboot.starter.orm.entity.Response;
import com.um.springboot.starter.orm.manager.BaseManager;
import com.um.springboot.starter.orm.params.ExportParams;
import com.um.springboot.starter.orm.params.PageParams;
import com.um.springboot.starter.utils.ExcelUtil;
import com.um.springboot.starter.utils.OrderUtil;
import com.um.springboot.starter.utils.PayUtil;
import com.um.springboot.starter.utils.StringUtil;
import com.um.weixin.pay.service.WxBasePayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Component
@Slf4j
public class RechargeOrderManager  extends BaseManager<RechargeOrderService>{

    @Autowired
    UserBillService userBillService;

    @Autowired
    PlatformBillService platformBillService;

    @Autowired
    PlatformProfitBillService platformProfitBillService;

    @Autowired
    WalletService walletService;

    @Autowired
    MemberUserService memberUserService;

    @Autowired
    WxManager wxManager;

    @Autowired
    WxBasePayService wxPayService;
    @Autowired
    BaofuPayService baofuPayService;

    @Autowired
    BaofuRefundService baofuRefundService;

    /**
     * 分页查询订单
     * @param pageParams
     * @return
     */
    public Response<Page<RechargeOrderItemVO>> page(PageParams pageParams) {
        Page<RechargeOrderItemVO> page = new Page<>();
        page.setPageNo(pageParams.getPageNo());
        page.setPageSize(pageParams.getPageSize());
        pageParams.getCondition().put("o.com_id",getComId());
        page = service.getCMSViewModelPageBySqlName(page, "get_recharge_order_page", "get_recharge_order_count",
                RechargeOrderItemVO.class, pageParams.getProperties(), pageParams.getValues(),
                pageParams.getRangeEntitys(), pageParams.getOrderNames(), pageParams.getSortOns());
        return Response.success(page);
    }

    @Transactional
    public Response refund(String orderNo, int amount) {
        RechargeOrder rechargeOrder = service.getEntity(new String[]{"order_no"}, new Object[]{orderNo});
        if(rechargeOrder == null){
            return Response.failed("充值订单不存在！");
        }

        if (StringUtil.getTrim(rechargeOrder.getStatus()).equals(PayEnum.Status.UnPayed.name())) {
            return Response.failed("订单未付款，不支持退款！");
        }

        int canCashoutBalance = walletService.getCanCashoutBalance(rechargeOrder.getMemberUserId(),rechargeOrder.getComId());
        if(canCashoutBalance <= 0){
            return Response.failed("可退金额为0元！");
        }

        if(amount > canCashoutBalance){
            return Response.failed("退款金额大于可退金额："+(canCashoutBalance/100.0)+"元！");
        }

        int payAmount = rechargeOrder.getPayAmount();//微信充值的订单金额
        int maxReturnAmount = payAmount - rechargeOrder.getReturnAmount();
        if(amount > maxReturnAmount){
            return Response.failed("退款金额大于充值支付金额,当前最高可退款金额为："+(maxReturnAmount/100.0));
        }

        String outTradeNo = StringUtil.getTrim(rechargeOrder.getOutTradeNo());
        boolean refundSuccess = true;
        String returnMsg = "";
        int totalAmount = 1;//非生产环境固定0.01元
        int returnAmount = 1;//非生产环境固定0.01元
        if(PayUtil.isProd()) {//生产环境按实际金额退款
            totalAmount = rechargeOrder.getPayAmount();
            returnAmount = amount;
        }

        if (rechargeOrder.getPayWay().equals(PayEnum.PayWay.Alipay.name())) {// 支付宝退款
            // TODO: 2023-06-13 支付宝退款待接入
//                Map refundResult = new HashMap();
//                try {
//                    refundResult = payService.refund(outTradeNo, payUtil.toDoubleAmount(amount));
//                    log.info("支付宝充值退款返回:" + JSONUtil.toJSONString(refundResult));
//                    refundSuccess = true;
//                } catch (Exception e) {
//                    returnMsg = StringUtil.getTrim(refundResult.get("sub_msg"));
//                }
        } else if (rechargeOrder.getPayWay().equals(PayEnum.PayWay.Wxpay.name())){
            /** todo 修改成宝付退款
            try {
                wxManager.getPayService(rechargeOrder.getComId());
                wxPayService.refundOrder(outTradeNo, OrderUtil.getWxOrderNo(), totalAmount, returnAmount);
            }catch (WxPayException ex){
                returnMsg = ex.getCustomErrorMsg();
                refundSuccess = false;
            }
             */
            try {
                String type = "recharge";
                String refundNo = OrderUtil.getWxOrderNo();
                baofuPayService.refundOrder(outTradeNo,refundNo, totalAmount, returnAmount,type,rechargeOrder.getComId()) ;

                BaofuRefund baofuRefund = new BaofuRefund();
                baofuRefund.setComId(rechargeOrder.getComId());
                baofuRefund.setRefundAmount(returnAmount);
                baofuRefund.setOutRefundNo(refundNo);
                baofuRefund.setRefundState("REFUND");
                baofuRefund.setOutTradeNo(outTradeNo);
                baofuRefund.setType(type);
                baofuRefundService.addRefund(baofuRefund);
                //回调执行
                refundSuccess = false;
                return Response.success("退款申请中！");
            }catch (ServiceException ex){
                returnMsg = ex.getMsg();
                refundSuccess = false;
            }
        }

        if(refundSuccess) {

            rechargeOrder.setReturnAmount(rechargeOrder.getReturnAmount() + amount);
            rechargeOrder.setReturnTime(new Date());
            service.update(rechargeOrder);

            //记录钱包流水，金额为充值到账金额
            Wallet wallet = new Wallet();
            wallet.setMemberUserId(rechargeOrder.getMemberUserId());
            wallet.setNo(OrderUtil.getOrderNo());
            wallet.setOrderNo(orderNo);
            wallet.setAmount(amount);
            wallet.setType(FinancialEnum.IncomeOrExpend.Expend.name());//收入支出类型：0-收入，1-支出
            wallet.setEvent(FinancialEnum.UserBillEvent.RechargeRedund.name());
            wallet.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
            wallet.setCreateTime(DateUtil.date());
            walletService.save(wallet);

            //记录账户流水，金额为支付金额
            UserBill userBill = new UserBill();
            userBill.setMemberUserId(rechargeOrder.getMemberUserId());
            userBill.setNo(OrderUtil.getOrderNo());
            userBill.setOutTradeNo(outTradeNo);
            userBill.setOrderNo(orderNo);
            userBill.setAmount(amount);
            userBill.setType(FinancialEnum.IncomeOrExpend.Income.name());//收入支出类型：0-收入，1-支出
            userBill.setEvent(FinancialEnum.UserBillEvent.RechargeRedund.name());
            userBill.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
            userBill.setCreateTime(DateUtil.date());
            userBillService.save(userBill);

            //插入平台账单流水：充值退回
            PlatformBill platformBill = new PlatformBill();
            platformBill.setNo(OrderUtil.getOrderNo());
            platformBill.setOutTradeNo(outTradeNo);
            platformBill.setOrderNo(orderNo);
            platformBill.setAmount(amount);
            platformBill.setType(FinancialEnum.IncomeOrExpend.Expend.name());//收入支出类型：0-收入，1-支出
            platformBill.setEvent(FinancialEnum.PlatformBillEvent.PackageRefund.name());
            platformBill.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
            platformBill.setCreateTime(DateUtil.date());
            platformBillService.save(platformBill);

            int giftAmount = (int)(rechargeOrder.getGiftAmount() * (returnAmount * 1.0 / rechargeOrder.getPayAmount()));
            //订单存在赠送金额，则需要按比例退掉赠送金额
            if(giftAmount > 0){

                Wallet giftWallet = new Wallet();
                giftWallet.setComId(rechargeOrder.getComId());
                giftWallet.setMemberUserId(rechargeOrder.getMemberUserId());
                giftWallet.setOrderNo(rechargeOrder.getOrderNo());
                giftWallet.setNo(OrderUtil.getOrderNo());
                giftWallet.setAmount(giftAmount);
                giftWallet.setType(FinancialEnum.IncomeOrExpend.Expend.name());
                giftWallet.setEvent(FinancialEnum.WalletBillEvent.GiftRefund.name());
                giftWallet.setStatus(FinancialEnum.BillStatus.Effective.name());
                giftWallet.setCreateTime(DateUtil.date());
                walletService.saveRow(giftWallet);

                PlatformProfitBill profitBill = new PlatformProfitBill();
                profitBill.setComId(rechargeOrder.getComId());
                profitBill.setNo(OrderUtil.getOrderNo());
                profitBill.setOutTradeNo(outTradeNo);
                profitBill.setOrderNo(orderNo);
                profitBill.setAmount(giftAmount);
                profitBill.setType(FinancialEnum.IncomeOrExpend.Income.name());//收入支出类型：0-收入，1-支出
                profitBill.setEvent(FinancialEnum.PlatformProfitBillEvent.GiftRefund.name());
                profitBill.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
                profitBill.setCreateTime(DateUtil.date());
                platformProfitBillService.saveRow(profitBill);
            }


            return Response.success();
        }else{
            return Response.failed("退款失败："+returnMsg);
        }
    }


    public Response exportPage(ExportParams exportParams) {

        List<RechargeOrderItemVO> list = service.getCMSViewModelListBySqlName("get_recharge_order_page", RechargeOrderItemVO.class,
                exportParams.getProperties(),exportParams.getValues(),
                exportParams.getRangeEntitys(),exportParams.getOrderNames(),exportParams.getSortOns(),
                new Object[]{exportParams.getStart(),exportParams.getLimit()});


        Map mapFormat = new Hashtable();
        mapFormat.put("create_time","yyyy-MM-dd HH:mm:ss");
        mapFormat.put("pay_time","yyyy-MM-dd HH:mm:ss");
        mapFormat.put("return_time","yyyy-MM-dd HH:mm:ss");
        mapFormat.put("recharge_amount","number");
        mapFormat.put("pay_amount","number");
        mapFormat.put("gift_amount","number");
        mapFormat.put("return_amount","number");

        String fileName = "Excel"+ com.um.springboot.starter.utils.DateUtil.getDateString(new Date(), "yyyyMMddHHmmss")+".xls";
        String path = service.getExportFilePath(fileName);
        List<String> columns = Arrays.asList("订单编号","订单时间","用户昵称","手机号码","商户订单号","支付时间","充值金额","赠送金额","支付金额","支付方式","支付状态","退款金额","退款时间");

        List<String> properties = Arrays.asList("order_no","create_time","nickname","mobile","out_trade_no","pay_time","recharge_amount","gift_amount","pay_amount","pay_way","status","return_amount","return_time");


        ExcelUtil.writeEntity(path, columns, list, properties, exportParams.getMapParam(), mapFormat, exportParams.getMapZero(),true);

        return Response.success(service.getDownFilePath(fileName));
    }

}
